package cn.mock.random;

import cn.mock.constant.Constant;
import cn.mock.enums.CharacterPool;
import cn.mock.utils.StringUtils;
import org.apache.commons.lang3.ObjectUtils;

import java.math.BigDecimal;
import java.util.Objects;

/**
 * @author JiaZH
 * @date 2024-01-12
 */
public class RandomBasic {

    /**
     * 返回一个随机的布尔值。
     *
     * @param min
     * @param max
     * @param cur
     * @return
     */
    public static Boolean getBoolean(Integer min, Integer max, Boolean cur) {
        if (Objects.nonNull(cur)) {
            min = ObjectUtils.defaultIfNull(min, 1);
            max = ObjectUtils.defaultIfNull(max, 1);
            return (Math.random() > 1.0 / (min + max) * min) != cur;
        }
        return Math.random() >= 0.5;
    }

    /**
     * 返回一个随机的布尔值。
     *
     * @param min
     * @param max
     * @param cur
     * @return
     */
    public static boolean getBool(Integer min, Integer max, Boolean cur) {
        return getBoolean(min, max, cur);
    }

    /**
     * 返回一个随机的自然数（大于等于 0 的整数）。
     *
     * @param min
     * @param max
     * @return
     */
    public static Integer getNatural(Integer min, Integer max) {
        min = ObjectUtils.defaultIfNull(min, 0);
        max = ObjectUtils.defaultIfNull(max, Integer.MAX_VALUE);
        return Math.toIntExact(Math.round(Math.random() * (max - min)) + min);
    }

    /**
     * 返回一个随机的整数。
     *
     * @param min
     * @param max
     * @return
     */
    public static Integer getInteger(Integer min, Integer max) {
        min = ObjectUtils.defaultIfNull(min, Integer.MIN_VALUE);
        max = ObjectUtils.defaultIfNull(max, Integer.MAX_VALUE);
        return Math.toIntExact(Math.round(Math.random() * (max - min)) + min);
    }

    /**
     * 返回一个随机的整数。
     *
     * @param min
     * @param max
     * @return
     */
    public static int getInt(Integer min, Integer max) {
        return getInteger(min, max);
    }

    /**
     * 返回一个随机的浮点数。
     *
     * @param min
     * @param max
     * @param dmin
     * @param dmax
     * @return
     */
    public static Double getDouble(Integer min, Integer max, Integer dmin, Integer dmax) {
        dmin = ObjectUtils.defaultIfNull(dmin, 0);
        dmin = Math.max(Math.min(dmin, 17), 0);
        dmax = ObjectUtils.defaultIfNull(dmax, 17);
        dmax = Math.max(Math.min(dmax, 17), 0);
        StringBuilder ret = new StringBuilder(getInteger(min, max) + ".");
        for (int i = 0, count = getNatural(dmin, dmax); i < count; i++) {
            ret.append((i < count - 1) ? getCharacter(CharacterPool.NUMBER.name()) : getCharacter(Constant.NUMBER_NO_ZERO));
        }
        return new BigDecimal(ret.toString()).doubleValue();
    }

    /**
     * 返回一个随机字符。
     *
     * @param pool
     * @return
     */
    public static Character getCharacter(String pool) {
        pool = CharacterPool.getPool(pool);
        return pool.charAt(getNatural(0, pool.length() - 1));
    }

    /**
     * 返回一个随机字符。
     *
     * @param pool
     * @return
     */
    public static char getChar(String pool) {
        return getCharacter(pool);
    }


    /**
     * 返回一个随机字符串。
     *
     * @param pool
     * @param min
     * @param max
     * @return
     */
    public static String getString(String pool, Integer min, Integer max) {
        int len;
        if (Objects.isNull(min) && Objects.isNull(max)) {
            len = getNatural(3, 7);
        } else {
            len = getNatural(min, max);
        }
        if (StringUtils.isBlank(pool)) {
            pool = CharacterPool.ALL.getPool();
        }
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < len; i++) {
            builder.append(getCharacter(pool));
        }
        return builder.toString();
    }

    /**
     * 返回一个随机字符串。
     * @param pool
     * @param len
     * @return
     */
    public static String getString(String pool, Integer len) {
        return getString(pool, len, len);
    }

    /**
     * 返回一个随机字符串。
     *
     * @return
     */
    public static String getStr() {
        return getString(null, null, null);
    }

    /**
     * 返回一个整型数组。
     *
     * @param start
     * @param stop
     * @param step
     * @return
     */
    public static Integer[] getRange(Integer start, Integer stop, Integer step) {
        start = ObjectUtils.defaultIfNull(start, 0);
        stop = ObjectUtils.defaultIfNull(stop, start);
        step = ObjectUtils.defaultIfNull(step, 1);

        start = +start;
        stop = +stop;
        step = +step;

        int len = (int) Math.max(Math.ceil((double) (stop - start) / step), 0);
        int idx = 0;
        Integer[] range = new Integer[len];

        while (idx < len) {
            range[idx++] = start;
            start += step;
        }
        return range;
    }

}
